Auth0 アカウントリンクを試す
Auth0は、デフォルトですべてのIDを別個のものとして扱います。
例えば、最初にAuth0データベースに対してログインし、次にGoogleでログインした場合、これら2つの試行はAuth0からは2人の別個のユーザーとして表示されます。
Auth0ではユーザーアカウントリンクというのがサポートされており、これによりユーザーは自分のアカウントのいずれかから認証され、アプリによって認識され、同じユーザープロファイルに関連付けられます。
利点は以下です。
- 個別のプロファイルを作成せずに、任意のIDプロバイダーでログインできる
- 新しいソーシャルログインまたはパスワードなしのログインを使用できますが、既存のプロファイルは引き続き使用できます
- パスワードなしのログインを使用して登録したユーザーが、より完全なプロファイルを持つアカウントにリンクできるようにします
- アプリがさまざまな接続に保存されているユーザープロファイルデータを取得できるようにします
引用元: Auth0ドキュメント ユーザーアカウントのリンク
では実際にアカウントリンクを行ったらどういう風に見えるのか試してみようと思います。
やってみる
Node.jsレギュラーWebアプリを使います。
Auth0にサンプルが用意されているため、使わせてもらいます。
- nodejsのバージョン:
v12.13.0
- OS: macOS Mojave 10.14.6
Auth0でアプリケーションの作成と設定
ダッシュボードで新規アプリケーションを作成します。
作成したアプリケーションの設定画面に行き、
Allowed Callback URLs
にhttp://localhost:3000/callback
Token Endpoint Authentication Method
に None
を設定しますします。
read:usersおよびupdate:usersスコープでAPIv2トークンを生成
Auth0 Management API`のアクセストークンを取得します。
read:users
, update:users
が必要です
$ curl --request POST \ > --url https://{your_auth0_domain}/oauth/token \ > --header 'content-type: application/json' \ > --data '{"client_id":"{your_client_id}","client_secret":"{your_client_secret}","audience":"https://{your_auth0_domain}/api/v2/","grant_type":"client_credentials"}' {"access_token":"アクセストークン","scope":"read:users update:users","expires_in":86400,"token_type":"Bearer"}
アクセストークンは次の手順で使用するのでコピーしておきます。
サンプルアプリのインストール
ターミナルを起動し、任意の場所に移動し、サンプルアプリをcloneします
$ cd {サンプルアプリのディレクトリ} $ git clone https://github.com/auth0-samples/auth0-link-accounts-sample.git $ cd auth0-link-accounts-sample/RegularWebApp/
sample.envファイルを自身の環境に合わせて修正します。
$ mv sample.env .env $ vi .env
AUTH0_CLIENT_ID=your-auth0-client-id AUTH0_CLIENT_SECRET=your-auth0-client-secret AUTH0_DOMAIN=your-auth0-domain AUTH0_CALLBACK_URL=http://localhost:3000/callback AUTH0_APIV2_TOKEN=your-auth0-api-v2-token
以下のコマンドでインストールし、アプリを立ち上げます。
$ npm install $ npm run start
ブラウザでhtt@://localhost:3000
にアクセスします
サンプルアプリの確認
アカウントリンク機能をサンプルアプリを使って試します。
LOGIN
ボタンをクリックし、Sign Up
タブをクリックします。
メールアドレスとパスワードを入力し、ユーザー登録を行います。
アプリの認証ダイアログが出ますが、許可
ボタンをクリックします。
ユーザー登録完了後、自動的にログインされます。
providerがauth0
, connectionがUsername-Password-Authentication
のユーザーが作成されました。
ユーザープロファイル
{ "created_at": "2020-03-03T10:11:24.532Z", "email": "mori.ryosuke@classmethod.jp", "email_verified": false, "identities": [ { "user_id": "5e5e2d4c9a67390d46dec91e", "provider": "auth0", "connection": "Username-Password-Authentication", "isSocial": false } ], "name": "mori.ryosuke@classmethod.jp", "nickname": "mori.ryosuke", ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ }
このユーザーにアカウントをリンクさせます。
※ サンプルアプリではメールアドレスの確認を終えていないとアカウントリンクされないので、最初のユーザーを作った後、メールボックスを確認してメール確認のリンクをクリックしておきましょう。
一度ログアウトします。
LOGIN
ボタンを押してダイアログを起動し、Log in with Google
を押してサンプルアプリにログインします。
※ アカウントリンクをするには、先ほど作ったユーザーと同じメールアドレスのgoogleアカウントが必要です。
進めていくとサンプルアプリにリダイレクトされますが、そこで Link Accounts
のダイアログが立ち上がるはずです。
Link
ボタンを押してリンクしましょう。
Linked Accounts
のボックスに先ほどまでなかった情報が表示されてます。リンクは成功していますね。
ユーザープロファイル
{ "created_at": "2020-03-03T11:14:38.766Z", "email": "mori.ryosuke@classmethod.jp", "email_verified": true, "family_name": "森", "given_name": "亮介", "identities": [ { "provider": "google-oauth2", "access_token": "ya29.a0Adw1xeX8rrDQrZT6fREYhtD2gscAOOZxRyGlktO-VowFIRfsV8eOkOTiNIChSRP-B47ZNfUi7r30ANiDo3wmuMOhs2Wq24hyqN_WCgFrXG0iQ8Z_ine6lDPWOdBcF9VOtmiOGYoIWVMVSXL1N1FI_NqNtLJQOqYBZarN", "expires_in": 3599, "user_id": "118272837942600975202", "connection": "google-oauth2", "isSocial": true }, { "profileData": { "email": "mori.ryosuke@classmethod.jp", "email_verified": true }, "user_id": "5e5e3a3acd78360d6f8522d1", "provider": "auth0", "connection": "Username-Password-Authentication", "isSocial": false } ], ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 以下省略 }
リンクされると、identitiesにリンク先、リンク元の情報が追加されます。
一旦ログアウトし、パスワードユーザーでログインしてみても、
プロフィール情報は同じです。
もうちょっと詳しく確認してみる
アカウントがリンクされることはわかりましたが、パスワードユーザーでログインしてもgoogleアカウントのプロファイルがメインで表示されています。
"user_id": "google-oauth2|118272837942600975202"
これは、サンプルアプリの中で、
googleアカウントのユーザーをプライマリーアカウント、パスワードユーザーをセカンダリーアカウントとしてリンクしたからです。
APIのドキュメントも確認してみます。
/api/v2/users/{id}/identities
Link two user accounts together forming a primary and secondary relationship. On successful linking, the endpoint returns the new array of the primary account identities.
リンクが成功すると、エンドポイントはプライマリアカウントIDの新しい配列を返します と書かれています。
APIの実行に必要なパラメーターは
id
: プライマリアカウントとして使用するuser_idbody
: セカンダリアカウントとして使用するユーザーのプロファイル情報provider
: セカンダリアカウントのプロバイダー名connection_id
: セカンダリアカウントのconnection_iduser_id
: セカンダリアカウントのuser_idlink_with
: リンクされるセカンダリアカウントのJWT。このパラメーターを送信する場合、provider、user_id、およびconnection_idは送信しない
です。
サンプルアプリでもこのAPIを実行しています。
コードはこちら
Auth0のダッシュボードでユーザー一覧を見てみると、
このように Connection
が google-oauth2
のユーザー一つだけになっています。
今回の手順でリンクしたプライマリーアカウントの情報が表示されていることがわかります。
最後に
Auth0のアカウントリンクをサンプルアプリを使って確認してみました。
サンプルアプリで行われたことは以下です。
- ユーザーを認証する
- メールアドレスを使用してユーザーを検索および識別します
- ユーザーにアカウントのリンクを促す
- メタデータの検証とマージ
- アカウントをリンクする
Auth0のデフォルトだと同じメールアドレスでも接続方法が違うと別ユーザーとして扱われますが、リンクしてしまえば一つのユーザーとして扱え、 他の接続方法のアカウントとプロファイル情報を共有できるため結構便利な機能だと思います。
アカウントをリンクする前にuser_metadata
とapp_metadata
をマージして共有することもできます。
※今回使用したサンプルアプリでも自動で行われるようになっています。
コードはこちら
このようなリンクを自身で実装するとなるとかなりの手間が想定されますが、Auth0ではAPIとして提供してくれているので容易に導入することができます。
記事の最初の方に記載したアカウントリンクの利点を生かしたいのであればぜひ試してみてください。